package com.tx.gateway.route.service.impl;

import com.tx.gateway.route.constants.RouteConstants;
import com.tx.gateway.route.service.DynRouteService;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

@Service
public class DynRouteServiceImpl implements DynRouteService, ApplicationEventPublisherAware {

    private ApplicationEventPublisher eventPublisher;

    @Resource
    private RouteDefinitionWriter routeDefinitionWriter;

    @Override
    public String addRoute(RouteDefinition routeDefinition) {
        routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
        this.eventPublisher.publishEvent(new RefreshRoutesEvent(this));
        return RouteConstants.SUCCESS;
    }

    @Override
    public String updateRoute(RouteDefinition routeDefinition) {
        try {
            deleteRoute(routeDefinition.getId()).subscribe();
        } catch (Exception e) {
            return "update fail, could not found the route, routeId:" + routeDefinition.getId();
        }
        try {
            routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
            eventPublisher.publishEvent(new RefreshRoutesEvent(this));
            return RouteConstants.SUCCESS;
        } catch (Exception e) {
            return "update route error: " + e.getMessage();
        }
    }

    @Override
    public Mono<String> deleteRoute(String routeId) {
        return this.routeDefinitionWriter.delete(Mono.just(routeId)).then(Mono.defer(() -> {
            this.eventPublisher.publishEvent(new RefreshRoutesEvent(this));
            return Mono.just(RouteConstants.SUCCESS);
        })).onErrorResume(t -> t instanceof Exception, t -> {
            t.printStackTrace();
            return Mono.just(t.getMessage());
        });
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.eventPublisher = applicationEventPublisher;
    }
}
